package com.sunfeng.n6;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author sunfeng
 * @date 2021/04/14 13:52
 **/
@Slf4j(topic = "c.ABAMethodTest2")
public class ABAMethodTest2 {
    static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);

    public static void main(String[] args) throws InterruptedException {
        log.debug("main start...");
        // 获取值 A
        String prev = ref.getReference();
        // 获取版本号
        int stamp = ref.getStamp();
        log.debug("版本 {}", stamp);
        // 如果中间有其它线程干扰，发生了 ABA 现象
        other();
        TimeUnit.MILLISECONDS.sleep(1000);
        // 尝试改为 C
        log.debug("change A->C {}", ref.compareAndSet(prev, "C", stamp, stamp + 1));
    }

    private static void other() throws InterruptedException {
        new Thread(() -> {
            log.debug("change A-> B {}", ref.compareAndSet(ref.getReference(), "B"
                    , ref.getStamp(), ref.getStamp() + 1));
            log.debug("跟新版本为{}", ref.getStamp());
        }).start();


        TimeUnit.MILLISECONDS.sleep(500);

        new Thread(() -> {
            log.debug("change B->A:{}", ref.compareAndSet(ref.getReference(), "A",
                    ref.getStamp(), ref.getStamp() + 1));
            log.debug("跟新版本为{}", ref.getStamp());
        }).start();

    }
}
